home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 26 / AMIGAplus Sonderheft 26 (2000)(Falke)(DE)(Track 1 of 2)[!].iso / Updates / Librarys / asyncioppc / source / async_ppc.c next >
C/C++ Source or Header  |  2000-07-04  |  13KB  |  522 lines

  1. #include <clib/dos_protos.h>
  2. #include <clib/exec_protos.h>
  3. #include <clib/powerpc_protos.h>
  4. #include <libraries/asyncio.h>
  5. #include <exec/memory.h>
  6. #include <string.h>
  7.  
  8. #define D_S(type,name) char a_##name[ sizeof( type )+3]; type *name=(type *)((LONG)(a_##name+3)&~3);
  9.  
  10. #ifndef MIN
  11. #define MIN(a,b) ((a)<(b)?(a):(b))
  12. #endif
  13.  
  14. static void copymem(UBYTE *s,UBYTE *d,ULONG len)
  15. {
  16. ULONG l=len&7;
  17. len-=l;
  18. while(l--) *(d++)=*(s++);
  19. while(len)
  20.     {
  21.     *(((double *)d)++)=*(((double *)s)++);
  22.     len-=8;
  23.     }
  24. }
  25.  
  26. static VOID AS_SendPacket(struct AsyncFile *file,APTR arg2)
  27. {
  28. file->af_Packet.sp_Pkt.dp_Port=&file->af_PacketPort;
  29. file->af_Packet.sp_Pkt.dp_Arg2=(LONG)arg2;
  30. PutXMsgPPC(file->af_Handler,&file->af_Packet.sp_Msg);
  31. file->af_PacketPending=TRUE;
  32. }
  33.  
  34. static LONG AS_WaitPacket(AsyncFile *file)
  35. {
  36. LONG bytes;
  37. if(file->af_PacketPending)
  38.     {
  39.     while(1)
  40.         {
  41.         file->af_PacketPort.mp_Flags=PA_SIGNAL;
  42.         RemovePPC((struct Node *)WaitPort(&file->af_PacketPort));
  43. /*
  44. This dummy call is absolutely necessary to avoid lock-up
  45. in some strange cases, e.g. accessing very long files !!, Dont remove it !!
  46. */
  47. //        SPrintF(0,0);
  48.         file->af_PacketPort.mp_Flags=PA_IGNORE;
  49.         file->af_PacketPending=FALSE;
  50.         bytes=file->af_Packet.sp_Pkt.dp_Res1;
  51.         if(bytes>=0) return bytes;
  52.         if(ErrorReport(file->af_Packet.sp_Pkt.dp_Res2,REPORT_STREAM,file->af_File,NULL)) return -1;
  53.         AS_SendPacket(file,file->af_Buffers[file->af_ReadMode?file->af_CurrentBuf:1-file->af_CurrentBuf]);
  54.         }
  55.     }
  56. SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);
  57. return file->af_Packet.sp_Pkt.dp_Res1;
  58. }
  59.  
  60. static VOID AS_RecordSyncFailure(struct AsyncFile *file)
  61. {
  62. file->af_LastRes1=file->af_Packet.sp_Pkt.dp_Res1;
  63. file->af_LastBytesLeft=file->af_BytesLeft;
  64. file->af_Packet.sp_Pkt.dp_Res1=-1;
  65. file->af_Packet.sp_Pkt.dp_Res2=IoErr();
  66. file->af_BytesLeft=0;
  67. }
  68.  
  69. static VOID AS_RequeuePacket(AsyncFile *file)
  70. {
  71. AddHeadPPC(&file->af_PacketPort.mp_MsgList,&file->af_Packet.sp_Msg.mn_Node);
  72. file->af_PacketPending=TRUE;
  73. }
  74.  
  75. struct AsyncFile *AS_OpenAsyncFH(BPTR handle,LONG mode,LONG bufferSize,BOOL closeIt)
  76. {
  77. FileHandle *fh;
  78. AsyncFile *file=NULL;
  79. BPTR lock=NULL;
  80. LONG blockSize,blockSize2;
  81. D_S(struct InfoData,infoData);
  82. if(mode==MODE_READ)
  83.     {
  84.     if(handle) lock=DupLockFromFH(handle);
  85.     }
  86. else
  87.     {
  88.     if(mode==MODE_APPEND)
  89.         {
  90.         if(handle)
  91.             {
  92.             if(Seek(handle,0,OFFSET_END)<0)
  93.                 {
  94.                 if(closeIt) Close(handle);
  95.                 handle=NULL;
  96.                 }
  97.             }
  98.         }
  99.     if(handle) lock=ParentOfFH(handle);
  100.     }
  101. if(handle)
  102.     {
  103.     blockSize=512;
  104.     blockSize2=1024;
  105.     if(lock)
  106.         {
  107.         if(Info(lock,infoData))
  108.             {
  109.             blockSize=infoData->id_BytesPerBlock;
  110.             blockSize2=blockSize*2;
  111.             bufferSize=((bufferSize+blockSize2-1)/blockSize2)*blockSize2;
  112.             }
  113.         UnLock(lock);
  114.         }
  115.     for(;;)
  116.         {
  117.         if(file=AllocVecPPC(sizeof(AsyncFile)+bufferSize+15,MEMF_PUBLIC|MEMF_ANY,0)) break;
  118.         else
  119.             {
  120.             if(bufferSize>blockSize2) bufferSize-=blockSize2;
  121.             else break;
  122.             }
  123.         }
  124.     if(file)
  125.         {
  126.         file->af_File=handle;
  127.         file->af_ReadMode=(mode==MODE_READ);
  128.         file->af_BlockSize=blockSize;
  129.         file->af_CloseFH=closeIt;
  130.         fh=(FileHandle *)BADDR(file->af_File);
  131.         file->af_Handler=fh->fh_Type;
  132.         file->af_BufferSize=(ULONG)bufferSize/2;
  133.         file->af_Buffers[0]=(UBYTE *)(((ULONG)file+sizeof(AsyncFile)+15)&0xfffffff0);
  134.         file->af_Buffers[1]=file->af_Buffers[0]+file->af_BufferSize;
  135.         file->af_CurrentBuf=0;
  136.         file->af_SeekOffset=0;
  137.         file->af_PacketPending=FALSE;
  138.         file->af_SeekPastEOF=FALSE;
  139.         file->af_PacketPort.mp_MsgList.lh_Head=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Tail;
  140.         file->af_PacketPort.mp_MsgList.lh_Tail=NULL;
  141.         file->af_PacketPort.mp_MsgList.lh_TailPred=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Head;
  142.         file->af_PacketPort.mp_Node.ln_Type=NT_MSGPORT;
  143.         file->af_PacketPort.mp_Node.ln_Name=NULL;
  144.         file->af_PacketPort.mp_Flags=PA_IGNORE;
  145.         file->af_PacketPort.mp_SigBit=SIGB_SINGLE;
  146.         file->af_PacketPort.mp_SigTask=FindTask(NULL);
  147.         file->af_Packet.sp_Pkt.dp_Link=&file->af_Packet.sp_Msg;
  148.         file->af_Packet.sp_Pkt.dp_Arg1=fh->fh_Arg1;
  149.         file->af_Packet.sp_Pkt.dp_Arg3=file->af_BufferSize;
  150.         file->af_Packet.sp_Pkt.dp_Res1=0;
  151.         file->af_Packet.sp_Pkt.dp_Res2=0;
  152.         file->af_Packet.sp_Msg.mn_Node.ln_Name=(STRPTR)&file->af_Packet.sp_Pkt;
  153.         file->af_Packet.sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
  154.         file->af_Packet.sp_Msg.mn_Length=sizeof(struct StandardPacket);
  155.         if(mode==MODE_READ)
  156.             {
  157.             file->af_Packet.sp_Pkt.dp_Type=ACTION_READ;
  158.             file->af_BytesLeft=0;
  159.             file->af_Offset=file->af_Buffers[1];
  160.             if(file->af_Handler) AS_SendPacket(file,file->af_Buffers[0]);
  161.             }
  162.         else
  163.             {
  164.             file->af_Packet.sp_Pkt.dp_Type=ACTION_WRITE;
  165.             file->af_BytesLeft=file->af_BufferSize;
  166.             file->af_Offset=file->af_Buffers[0];
  167.             }
  168.         }
  169.     else
  170.         {
  171.         if(closeIt) Close(handle);
  172.         }
  173.     }
  174. return file;
  175. }
  176.  
  177. struct AsyncFile * __saveds OpenAsyncPPC(struct AsyncIOBase *base,STRPTR fileName,LONG mode,LONG bufferSize)
  178. {
  179. static const WORD PrivateOpenModes[]={MODE_OLDFILE,MODE_NEWFILE,MODE_READWRITE};
  180. BPTR handle;
  181. AsyncFile *file=NULL;
  182. if(handle=Open(fileName,PrivateOpenModes[mode]))
  183.     {
  184.     if(!(file=AS_OpenAsyncFH(handle,mode,bufferSize,TRUE))) Close(handle);
  185.     }
  186. return file;
  187. }
  188.  
  189. struct AsyncFile * __saveds OpenAsyncFromFHPPC(struct AsyncIOBase *base,BPTR handle,LONG mode,LONG bufferSize)
  190. {
  191. return AS_OpenAsyncFH(handle,mode,bufferSize,FALSE);
  192. }
  193.  
  194. LONG __saveds CloseAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file)
  195. {
  196. LONG result;
  197. if(file)
  198.     {
  199.     result=AS_WaitPacket(file);
  200.     if(result>=0)
  201.         {
  202.         if(!file->af_ReadMode)
  203.             {
  204.             if(file->af_BufferSize>file->af_BytesLeft)
  205.                 {
  206.                 result=Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft);
  207.                 }
  208.             }
  209.         }
  210.     if(file->af_CloseFH) Close(file->af_File);
  211.     FreeVecPPC(file);
  212.     }
  213. else result=-1;
  214. return result;
  215. }
  216.  
  217. LONG __saveds ReadAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  218. {
  219. LONG totalBytes=0;
  220. LONG bytesArrived;
  221. while(numBytes>file->af_BytesLeft)
  222.     {
  223.     copymem(file->af_Offset,buffer,file->af_BytesLeft);
  224.     numBytes-=file->af_BytesLeft;
  225.     buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
  226.     totalBytes+=file->af_BytesLeft;
  227.     file->af_BytesLeft=0;
  228.     bytesArrived=AS_WaitPacket(file);
  229.     if(bytesArrived<=0)
  230.         {
  231.         if(bytesArrived==0) return(totalBytes);
  232.         return -1;
  233.         }
  234.     AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
  235.     if(file->af_SeekOffset>bytesArrived) file->af_SeekOffset=bytesArrived;
  236.     file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+file->af_SeekOffset;
  237.     file->af_CurrentBuf=1-file->af_CurrentBuf;
  238.     file->af_BytesLeft=bytesArrived-file->af_SeekOffset;
  239.     file->af_SeekOffset=0;
  240.     }
  241. copymem(file->af_Offset,buffer,numBytes);
  242. file->af_BytesLeft-=numBytes;
  243. file->af_Offset+=numBytes;
  244. return totalBytes+numBytes;
  245. }
  246.  
  247. LONG __saveds PeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  248. {
  249. if(!file->af_BytesLeft)
  250.     {
  251.     LONG bytes;
  252.     if((bytes=ReadAsyncPPC(base,file,&bytes,1))<=0) return bytes;
  253.     --file->af_Offset;
  254.     ++file->af_BytesLeft;
  255.     }
  256. numBytes=MIN(numBytes,file->af_BytesLeft);
  257. copymem(file->af_Offset,buffer,numBytes);
  258. return numBytes;
  259. }
  260.  
  261. LONG __saveds ReadCharAsyncPPC(struct AsyncIOBase *base,AsyncFile *file)
  262. {
  263. UBYTE    ch;
  264. if(file->af_BytesLeft)
  265.     {
  266.     ch=*file->af_Offset;
  267.     --file->af_BytesLeft;
  268.     ++file->af_Offset;
  269.     return ch;
  270.     }
  271. if(ReadAsyncPPC(base,file,&ch,1)>0) return ch;
  272. return -1;
  273. }
  274.  
  275. STRPTR __saveds FGetsLenAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes,LONG *len)
  276. {
  277. UBYTE *p;
  278. LONG    length=0;
  279. p=(UBYTE *)buf;
  280. if(--numBytes<=0) return 0;
  281. while(TRUE)
  282.     {
  283.     UBYTE *ptr;
  284.     LONG i,count;
  285.     ptr=(UBYTE *)file->af_Offset;
  286.     if(count=file->af_BytesLeft)
  287.         {
  288.         count=MIN(count,numBytes);
  289.         for(i=0;(i<count)&&(*ptr!='\n');++i) *p++=*ptr++;
  290.         length+=i;
  291.         if(i<count)
  292.             {
  293.             *p++='\n';
  294.             ++i;
  295.             length+=1;
  296.             }
  297.         file->af_BytesLeft-=i;
  298.         file->af_Offset+=i;
  299.         if((i>=numBytes)||(*(p-1)=='\n')) break;
  300.         numBytes-=i;
  301.         }
  302.     if(ReadAsyncPPC(base,file,p,1)<1) break;
  303.     --numBytes;
  304.     ++length;
  305.     if(*p++=='\n') break;
  306.     }
  307. *p='\0';
  308. *len=length;
  309. if(p==(UBYTE *)buf) return 0;
  310. return buf;
  311. }
  312.  
  313. STRPTR __saveds FGetsAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes)
  314. {
  315. LONG len;
  316. return FGetsLenAsyncPPC(base,file,buf,numBytes,&len);
  317. }
  318.  
  319. LONG __saveds ReadLineAsyncPPC(struct AsyncIOBase *base,AsyncFile *file,APTR buffer,LONG bufSize)
  320. {
  321. LONG    len;
  322. if(FGetsLenAsyncPPC(base,file,buffer,bufSize,&len))
  323.     {
  324.     UBYTE *end;
  325.     end=((UBYTE *)buffer)+len-1;
  326.     if(*end!='\n')
  327.         {
  328.         UBYTE    ch=0;
  329.         while(TRUE)
  330.             {
  331.             UBYTE *ptr;
  332.             LONG i,count;
  333.             ptr=(UBYTE *)file->af_Offset;
  334.             if(count=file->af_BytesLeft)
  335.                 {
  336.                 for(i=0;(i<count)&& (*ptr!='\n');++i,++ptr)
  337.                     {
  338.                     }
  339.                 if(i<count)
  340.                     {
  341.                     ch='\n';
  342.                     ++i;
  343.                     }
  344.                 file->af_BytesLeft-=i;
  345.                 file->af_Offset+=i;
  346.                 if(i<count) break;
  347.                 }
  348.             if(ReadAsyncPPC(base,file,&ch,1)<1) break;
  349.             if(ch=='\n') break;
  350.             }
  351.         if(ch=='\n')
  352.             {
  353.             *end++='\n';
  354.             *end='\0';
  355.             }
  356.         }
  357.     }
  358. return len;
  359. }
  360.  
  361. static __saveds ULONG GetFileSize(AsyncFile *file,LONG *size)
  362. {
  363. D_S(struct FileInfoBlock,fib);
  364. if(!ExamineFH(file->af_File,fib))
  365.     {
  366.     AS_RecordSyncFailure(file);
  367.     return FALSE;
  368.     }
  369. *size=fib->fib_Size;
  370. return TRUE;
  371. }
  372.  
  373. LONG __saveds SeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,LONG position,LONG mode)
  374. {
  375. LONG current,target,roundTarget,filePos;
  376. LONG minBuf,maxBuf,bytesArrived,diff;
  377. LONG fileSize;
  378. bytesArrived=AS_WaitPacket(file);
  379. if(bytesArrived<0)
  380.     {
  381.     if(file->af_SeekPastEOF)
  382.         {
  383.         bytesArrived=file->af_LastRes1;
  384.         file->af_BytesLeft=file->af_LastBytesLeft;
  385.         }
  386.     else return -1;
  387.     }
  388. if(file->af_ReadMode)
  389.     {
  390.     filePos=Seek(file->af_File,0,OFFSET_CURRENT);
  391.     if(filePos<0)
  392.         {
  393.         AS_RecordSyncFailure(file);
  394.         return -1;
  395.         }
  396.     current=filePos-(file->af_BytesLeft+bytesArrived)+file->af_SeekOffset;
  397.     if(mode==MODE_CURRENT) target=current+position;
  398.     else if(mode==MODE_START) target=position;
  399.     else 
  400.         {
  401.         if(!GetFileSize(file,&fileSize)) return -1;
  402.         target=fileSize+position;
  403.         }
  404.     minBuf=current-(LONG)(file->af_Offset-file->af_Buffers[1-file->af_CurrentBuf]);
  405.     maxBuf=current+file->af_BytesLeft+bytesArrived;
  406.     diff=target-current;
  407.     if((target<minBuf)||(target>=maxBuf))
  408.         {
  409.         if(target>=maxBuf)
  410.             {
  411.             if(!GetFileSize(file,&fileSize)) return -1;
  412.             if(target>fileSize)
  413.                 {
  414.                 file->af_SeekPastEOF=TRUE;
  415.                 SetIoErr(ERROR_SEEK_ERROR);
  416.                 AS_RecordSyncFailure(file);
  417.                 return -1;
  418.                 }
  419.             }
  420.         roundTarget=(target/file->af_BlockSize)*file->af_BlockSize;
  421.         if(Seek(file->af_File,roundTarget-filePos,OFFSET_CURRENT)<0)
  422.             {
  423.             AS_RecordSyncFailure(file);
  424.             return -1;
  425.             }
  426.         AS_SendPacket(file,file->af_Buffers[0]);
  427.         file->af_SeekOffset=target-roundTarget;
  428.         file->af_BytesLeft=0;
  429.         file->af_CurrentBuf=0;
  430.         file->af_Offset=file->af_Buffers[1];
  431.         }
  432.     else if((target<current)||(diff<=file->af_BytesLeft))
  433.         {
  434.         AS_RequeuePacket(file);
  435.         file->af_BytesLeft-=diff;
  436.         file->af_Offset+=diff;
  437.         if(file->af_SeekPastEOF) file->af_Packet.sp_Pkt.dp_Res1=file->af_LastRes1;
  438.         }
  439.     else
  440.         {
  441.         AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
  442.         diff-=file->af_BytesLeft-file->af_SeekOffset;
  443.         file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+diff;
  444.         file->af_BytesLeft=bytesArrived-diff;
  445.         file->af_SeekOffset=0;
  446.         file->af_CurrentBuf=1-file->af_CurrentBuf;
  447.         }
  448.     }
  449. else
  450.     {
  451.     if(file->af_BufferSize>file->af_BytesLeft)
  452.         {
  453.         if(Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft)<0)
  454.             {
  455.             AS_RecordSyncFailure(file);
  456.             return -1;
  457.             }
  458.         }
  459.     current=Seek(file->af_File,position,mode);
  460.     if(current<0)
  461.         {
  462.         AS_RecordSyncFailure(file);
  463.         return -1;
  464.         }
  465.     file->af_BytesLeft=file->af_BufferSize;
  466.     file->af_CurrentBuf=0;
  467.     file->af_Offset=file->af_Buffers[0];
  468.     }
  469. if(file->af_SeekPastEOF) file->af_SeekPastEOF=FALSE;
  470. SetIoErr(0);
  471. return current;
  472. }
  473.  
  474. LONG __saveds WriteAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  475. {
  476. LONG totalBytes=0;
  477. if(!file->af_Handler)
  478.     {
  479.     file->af_Offset=file->af_Buffers[0];
  480.     file->af_BytesLeft=file->af_BufferSize;
  481.     return numBytes;
  482.     }
  483. while(numBytes>file->af_BytesLeft)
  484.     {
  485.     if(file->af_BytesLeft)
  486.         {
  487.         copymem(buffer,file->af_Offset,file->af_BytesLeft);
  488.         numBytes-=file->af_BytesLeft;
  489.         buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
  490.         totalBytes+=file->af_BytesLeft;
  491.         }
  492.     if(AS_WaitPacket(file)<0) return -1;
  493.     AS_SendPacket(file,file->af_Buffers[file->af_CurrentBuf]);
  494.     file->af_CurrentBuf=1-file->af_CurrentBuf;
  495.     file->af_Offset=file->af_Buffers[file->af_CurrentBuf];
  496.     file->af_BytesLeft=file->af_BufferSize;
  497.     }
  498. copymem(buffer,file->af_Offset,numBytes);
  499. file->af_BytesLeft-=numBytes;
  500. file->af_Offset+=numBytes;
  501. return totalBytes+numBytes;
  502. }
  503.  
  504. LONG __saveds WriteCharAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,ULONG ch)
  505. {
  506. UBYTE    c;
  507. if(file->af_BytesLeft)
  508.     {
  509.     *file->af_Offset=ch;
  510.     --file->af_BytesLeft;
  511.     ++file->af_Offset;
  512.     return 1;
  513.     }
  514. c=ch;
  515. return WriteAsyncPPC(base,file,&c,1);
  516. }
  517.  
  518. LONG __saveds WriteLineAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR line)
  519. {
  520. return WriteAsyncPPC(base,file,line,strlen(line));
  521. }
  522.